#pragma once
#include <iostream>
#include <regex>
#include <arpa/inet.h>
#include <netdb.h>
#include "Protocol.hpp"
#include "Comm.hpp"

using namespace protocol_ns;

// class Proxy
// {
// public:
//     Proxy()
//     {
//     }
//     Response Excute(const Request &req)
//     {
//         Response resp(0, 0);

//         switch (req._oper)
//         {
//         case '+':
//             resp._result = req._x + req._y;
//             break;
//         case '-':
//             resp._result = req._x - req._y;
//             break;
//         case '*':
//             resp._result = req._x + req._y;
//             break;
//         case '/':
//         {
//             if (req._y == 0)
//             {
//                 resp._code = 1;
//             }
//             else
//             {
//                 resp._result = req._x / req._y;
//             }
//         }
//         break;
//         case '%':
//         {
//             if (req._y == 0)
//             {
//                 resp._code = 2;
//             }
//             else
//             {
//                 resp._result = req._x % req._y;
//             }
//         }
//         break;
//         default:
//             resp._code = 3;
//             break;
//         }
//         return resp;
//     }
//     ~Proxy()
//     {
//     }

// private:
// };

class Proxy
{
    struct URL
    {
        std::string host;
        std::string path;
    };
    // 域名解析函数
    std::string resolve_hostname(const std::string &hostname)
    {
        struct addrinfo hints, *res;
        int status;
        char ipstr[INET6_ADDRSTRLEN];

        // 初始化 hints 结构体
        std::memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;     // 获取 IPv4 或 IPv6 地址
        hints.ai_socktype = SOCK_STREAM; // 默认类型是流套接字

        // 调用 getaddrinfo 进行域名解析
        status = getaddrinfo(hostname.c_str(), nullptr, &hints, &res);
        if (status != 0)
        {
            std::cerr << "getaddrinfo error: " << gai_strerror(status) << std::endl;
            return "";
        }

        // 遍历返回的结果并返回第一个有效的 IP 地址
        for (struct addrinfo *p = res; p != nullptr; p = p->ai_next)
        {
            void *addr;

            if (p->ai_family == AF_INET)
            { // IPv4
                struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
                addr = &(ipv4->sin_addr);
            }
            else if (p->ai_family == AF_INET6)
            { // IPv6
                struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
                addr = &(ipv6->sin6_addr);
            }
            else
            {
                continue;
            }

            // 将地址转换为字符串
            inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
            freeaddrinfo(res);         // 释放内存
            return std::string(ipstr); // 返回解析到的 IP 地址
        }

        freeaddrinfo(res); // 释放内存
        return "";
    }

    // URL 解析函数
    URL parseUrl(const std::string &url)
    {
        std::regex urlPattern(R"((http[s]?:\/\/)?([^\/:]+)(:[0-9]+)?(\/[^ ]*)?)");
        std::smatch match;

        URL parsedUrl;

        if (std::regex_match(url, match, urlPattern))
        {
            // 提取 host 和 path
            parsedUrl.host = match[2];                                // 主机名或IP地址
            parsedUrl.path = match[4].matched ? match[4].str() : "/"; // 默认路径为 "/"

            // 如果路径没有以 / 开头，补充上
            if (parsedUrl.path.empty() || parsedUrl.path[0] != '/')
            {
                parsedUrl.path = "/" + parsedUrl.path;
            }

            // 如果 host 是域名，进行域名解析
            if (parsedUrl.host.find_first_not_of("0123456789.") != std::string::npos)
            { // 判断是否是域名
                std::string ip = resolve_hostname(parsedUrl.host);
                if (!ip.empty())
                {
                    parsedUrl.host = ip; // 将解析后的 IP 地址赋值给 host
                }
            }
        }

        return parsedUrl;
    }

    // URL parseUrl(const std::string &url)
    // {
    //     std::regex urlPattern(R"((http[s]?:\/\/)?([^\/:]+)(:[0-9]+)?(\/[^ ]*)?)");
    //     std::smatch match;

    //     URL parsedUrl;

    //     if (std::regex_match(url, match, urlPattern))
    //     {
    //         // 提取 host 和 path
    //         parsedUrl.host = match[2];                                // 主机名或IP地址
    //         parsedUrl.path = match[4].matched ? match[4].str() : "/"; // 默认路径为 "/"

    //         // 如果路径没有以 / 开头，补充上
    //         if (parsedUrl.path.empty() || parsedUrl.path[0] != '/')
    //         {
    //             parsedUrl.path = "/" + parsedUrl.path;
    //         }
    //     }

    //     return parsedUrl;
    // }
    std::string receive_data(int sockfd)
    {
        int wait_time = 50000;
        char buffer[40960];
        std::string response = "";
        ssize_t bytes_received;

        // 使用 select 进行事件驱动的等待
        fd_set readfds;
        struct timeval timeout;
        timeout.tv_sec = 0; // 设置超时时间
        timeout.tv_usec = 70000;

        while (true)
        {
            FD_ZERO(&readfds);        // 清空 readfds
            FD_SET(sockfd, &readfds); // 将 sockfd 加入监听集合

            // 等待套接字上有数据可读
            int activity = select(sockfd + 1, &readfds, nullptr, nullptr, &timeout);

            if (activity == -1)
            {
                std::cerr << "select() failed!" << std::endl;
                return "";
            }
            else if (activity == 0)
            {
                // 超时，可以选择继续等待或者退出
                std::cout << "No data available, retrying..." << std::endl;
                if (--wait_time == 0)
                {
                    std::cout << wait_time << std::endl;
                    break;
                }
                else
                    continue;
            }

            // 有数据可以读取
            if (FD_ISSET(sockfd, &readfds))
            {
                bytes_received = recv(sockfd, buffer, sizeof(buffer), 0);
                if (bytes_received > 0)
                {
                    std::cout << "------------------------recv msg---------------" << std::endl;
                    response.append(buffer, bytes_received);
                }
                else if (bytes_received == 0)
                {
                    // 连接关闭
                    std::cout << wait_time << std::endl;
                    break;
                }
                else
                {
                    std::cerr << "recv() error: " << strerror(errno) << std::endl;
                    break;
                }
            }
        }

        return response;
    }

public:
    Proxy()
    {
    }
    Response Excute(Request &req)
    {
        std::cout << "------------------------Excute---------------" << std::endl;
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1)
        {
            std::cerr << "Socket creation failed!" << std::endl;
            return Response(-1, "Socket creation failed!");
        }
        std::string port("80");
        size_t colon_pos = req._url.find(':', 6);
        if (colon_pos != std::string::npos)
        {
            // 查找第一个 '/' 或字符串的结束位置（避免包含路径部分）
            size_t path_pos = req._url.find('/', colon_pos);

            // 如果没有找到 '/'，说明这是一个没有路径的简单URL，直接删除端口号
            if (path_pos == std::string::npos)
            {
                port = req._url.substr(colon_pos + 1);
                req._url = req._url.substr(0, colon_pos); // 删除端口号及其后的内容
            }
            else
            {
                port = req._url.substr(colon_pos + 1, path_pos - colon_pos - 1);
                // 删除端口号部分（:8888）及其后的内容
                req._url = req._url.substr(0, colon_pos) + req._url.substr(path_pos);
            }
        }
        std::cout << req._url << std::endl;
        std::cout << port << std::endl;
        URL parsed = parseUrl(req._url);
        std::string host = parsed.host;
        struct sockaddr_in server_addr;

        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(std::stoi(port));
        server_addr.sin_addr.s_addr = inet_addr(host.c_str());
        std::cout << "remote addr:" << host.c_str() << std::endl;
        if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
        {
            std::cerr << "Connection failed!:" << strerror(errno) << std::endl;
            close(sockfd);
            return Response(1, "Connection failed!");
        }
        std::cout << "------------------------Connection success---------------" << std::endl;
        // 构造 HTTP GET 请求
        std::stringstream request;
        request << req._method << " " << parsed.path << " " << req._version << "\r\n"
                << "Host: " << host << "\r\n"
                << "Accept: " << req._accept << "\r\n"
                << "Accept-Encoding: " << req._accept_Encoding << "\r\n";
                std::cout<<request.str()<<std::endl;
        if (!req._cookies.empty())
        {
            request << "Cookie: " << req._cookies << "\r\n";
        }
        request << "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\r\n";
        request << "Connection: keep-alive\r\n";
        request << "Referer: " << req._url << "\r\n";
        request << "\r\n"; // 请求体为空
        // 发送 HTTP 请求
        std::string requestStr = request.str();
        send(sockfd, requestStr.c_str(), requestStr.length(), 0);
        std::cout << "------------------------send success---------------" << std::endl;

        // 接收响应
        // char buffer[40960];
        // std::string response = "";
        // ssize_t bytes_received;
        // SetNonBlock(sockfd);
        // sleep(1);
        // while ((bytes_received = recv(sockfd, buffer, sizeof(buffer), 0)) > 0)
        // {
        //     std::cout << "------------------------recv msg---------------" << std::endl;
        //     response.append(buffer, bytes_received);
        // }

        std::string response = receive_data(sockfd);
        // std::cout << "response str:" << std::endl;
        // std::cout << response << std::endl;
        response += "\r\n\r\n";
        std::cout << "------------------------close remote socket---------------" << std::endl;
        close(sockfd);
        return Response(0, response);
    }
    ~Proxy()
    {
    }
};